Technical Q&A QA1286
Sequence Grabber - How do I save user settings as CFPreferences?


Q: アプリケーションのユーザが Sequence Grabber 環境設定を設定できるように SGSettingDialog を使用しています。設定が行われたら Video チャネルに対して SGGetChannelSettings を呼び出して、後で使用できるように保存しておく設定を取得します。SGGetChannelSettings は設定を UserData として返します。これらの UserData 設定を CFPreferences API を使用して保存し、後でその設定を復元するにはどうすればよいのでしょうか。

A: 関数 CFPreferencesSetAppValue および CFPreferencesCopyAppValue は、Mac OS X で環境設定の作成と取得を行うための最も簡単な方法です。Sequence Grabber Settings API はチャンネルやパネルのコンポーネントに働きかけ、ユーザによる設定の内容を集めて UserData として戻します。

UserData は、UserDataRecord、つまり SeqGrabComponent または SGChannel のインスタンスに固有の設定を含む項目の配列へのポインタとして定義されています(図 1 参照)。

図 1

struct UserDataRecord {
  long data[1];
};
typedef struct UserDataRecord UserDataRecord;
typedef UserDataRecord *      UserData;

NewUserDataFromHandlePutUserDataIntoHandle といった User Data 関数を呼び出すことで、Sequence Grabber 設定を保存し、後で復元するために、UserData から CFPropertyList オブジェクトを作成したり、CFPropertyList オブジェクトから UserData を作成したりできます。

リスト 1 に示す GetSettingsPreferenceSetSettingsPreference の関数は、UserData を CFPreferences として保存し、復元する 1 つの手法を示します。リスト 2 には、これらのサンプル関数を SGGetChannelSettings および SGSetChannelSettings の呼び出しと組み合わせて使用する方法を示します。

リスト 1.

// GetSettingsPreference
// 指定されたキーの環境設定を QuickTime の UserData として返す
// 返された UserData は自分で破棄する必要がある
OSErr GetSettingsPreference(CFStringRef inKey, UserData *outUserData)
{
  CFPropertyListRef theCFSettings;
  Handle            theHandle = NULL;
  UserData          theUserData = NULL;
  OSErr             err = paramErr;

  // 環境設定から新しい設定を読み込む
  theCFSettings = CFPreferencesCopyAppValue(inKey,
                                         kCFPreferencesCurrentApplication);
  if (theCFSettings) {
    err = PtrToHand(CFDataGetBytePtr((CFDataRef)theCFSettings), &theHandle,
                    CFDataGetLength((CFDataRef)theCFSettings));
        
    CFRelease(theCFSettings);
    if (theHandle) {
      err = NewUserDataFromHandle(theHandle, &theUserData);
      if (theUserData) {
        *outUserData = theUserData;
      }
      DisposeHandle(theHandle);
    }
  }

  return err;
}

// SaveSettingsPreference
// QuickTime の UserData から、指定されたキーの環境設定を保存
OSErr SaveSettingsPreference(CFStringRef inKey, UserData inUserData)
{
  CFDataRef theCFSettings;
  Handle    hSettings;
  OSErr     err;
    
  if (NULL == inUserData) return paramErr;
    
  hSettings = NewHandle(0);
  err = MemError();
    
  if (noErr == err) {
    err = PutUserDataIntoHandle(inUserData, hSettings); 
        
    if (noErr == err) {
      HLock(hSettings);
    
      theCFSettings = CFDataCreate(kCFAllocatorDefault,
                                   (UInt8 *)*hSettings,
                                   GetHandleSize(hSettings));
      if (theCFSettings) {
        CFPreferencesSetAppValue(inKey, theCFSettings,
                                 kCFPreferencesCurrentApplication);
        CFPreferencesAppSynchronize(kCFPreferencesCurrentApplication);
        CFRelease(theCFSettings);
      }
    }

    DisposeHandle(hSettings);
  }

  return err;
}

リスト 2.

UserData mySGVideoSettings = NULL;

...

// キー「sgVideoSettings」を使用して設定を取得する
GetSettingsPreference(CFSTR("sgVideoSettings"), &mySGVideoSettings);
if (mySGVideoSettings) {
  // 保存した環境設定を使用して SGChannel を設定する
  SGSetChannelSettings(theSGInstance, theVideoChannel,
                       mySGVideoSettings, 0);
  DisposeUserData(mySGVideoSettings);
}

// 設定ダイアログを呼び出して、さらに設定を行えるようにする
SGSettingsDialog( ... );

// ユーザが設定した SGChannel の設定を取得する
SGGetChannelSettings(theSGInstance, theVideoChannel, &mySGVideoSettings, 0);
// キー「sgVideoSettings」に使用して設定を保存する
SaveSettingsPreference(CFSTR("sgVideoSettings"), mySGVideoSettings);
DisposeUserData(mySGVideoSettings);

...

参考資料:


[2003 年 9 月 4 日]